# pip install fastapi[all]
# pip install imageio-ffmpeg
# pip install ffmpeg-python
# pip install requests
# pip install scenedetect
# pip install opencv-python-headless

from fastapi import FastAPI, BackgroundTasks
import os
import re
import ffmpeg
import requests
from scenedetect import detect, ContentDetector
from urllib.parse import urlparse
from tiktok_downloader import TikTokDownloader
from google_speech import GoogleSpeechTranscriber
from json_parser import extract_json_from_string
app = FastAPI()


# 任务状态
status = False
# 本地存储路径
# OUTPUT_MP3_DIR = "/Users/zhans.dong/data/ruoyi/mp3"
# OUTPUT_IMG_DIR = "/Users/zhans.dong/data/ruoyi/image"
# DOWNLOAD_DIR = "/Users/zhans.dong/data/ruoyi/mp4"
# OUTPUT_MP3_DIR = "E:\\ruoyi\\mp3"
# OUTPUT_IMG_DIR = "E:\\ruoyi\\image"
# DOWNLOAD_DIR = "E:\\ruoyi\\uploadPath"
OUTPUT_MP3_DIR = "/home/data/mp3"
OUTPUT_IMG_DIR = "/home/data/image"
DOWNLOAD_DIR = "/home/data/mp4"

os.makedirs(OUTPUT_MP3_DIR, exist_ok=True)
os.makedirs(OUTPUT_IMG_DIR, exist_ok=True)
os.makedirs(DOWNLOAD_DIR, exist_ok=True)


# ============================
# 1️⃣ Java 触发完整流程
# ============================
@app.get("/process-video")
async def process_video(url: str, video_id: str, background_tasks: BackgroundTasks):
    global status
    response = not status  # Java 期望返回 `!status`
    if status:
        return {"status": response, "message": "任务正在进行"}

    status = True
    background_tasks.add_task(video_pipeline, url, video_id)  # 异步执行
    return {"status": response, "message": "任务已提交"}


# ============================
# 2️⃣ 仅解析（Java 传入已下载视频）
# ============================
@app.get("/process-local-video")
async def process_local_video(video_path: str, video_id: str, background_tasks: BackgroundTasks):
    global status
    response = not status
    if status:
        return {"status": response, "message": "任务正在进行"}

    status = True
    background_tasks.add_task(parse_video_pipeline, video_path, video_id)
    return {"status": response, "message": "任务已提交"}


# ============================
# 3️⃣ AI 解析（Java 传入 mp3）
# ============================
@app.get("/process-ai")
async def process_ai(mp3_path: str, video_id: str, background_tasks: BackgroundTasks):
    global status
    response = not status
    if status:
        return {"status": response, "message": "任务正在进行"}

    status = True
    background_tasks.add_task(ai_pipeline, mp3_path, video_id)
    return {"status": response, "message": "任务已提交"}


# ============================
# 4️⃣ 视频下载 & 解析流程（异步）
# ============================
def video_pipeline(url, video_id):
    """ 负责完整的下载、解析、AI 处理流程 """
    try:
        # ① 下载视频
        if is_url(url):
          video_path = download_file(url, video_id)
        else:
          video_path = url  # 直接使用本地路径
    
        # ② 解析视频
        if not video_path or len(video_path) <= 5:
          return;
        audio_path, keyframes = extract_audio_and_frames(video_path, video_id)
        if not audio_path or len(audio_path) <= 5:
          return;
        # file_size = os.path.getsize(audio_file_path)
        # if file_size > 6.99 * 1024 * 1024:
        #     return {"error": "音频文件大小不能超过 7MB，请上传更小的文件。"}
        # ③ 继续 AI 解析
        ai_pipeline(audio_path, video_id)

    finally:
        global status
        status = False  # 任务结束


def parse_video_pipeline(video_path, video_id):
    """ 负责解析本地视频 """
    try:
        audio_path, keyframes = extract_audio_and_frames(video_path, video_id)
        ai_pipeline(audio_path, video_id)
    finally:
        global status
        status = False



# ============================
# 5️⃣ 下载视频
# ============================

def is_url(path):
    """ 判断路径是否是URL """
    return path.startswith("http://") or path.startswith("https://")


def download_file(video_url, video_id):
    """ 下载远程文件到本地 """
    video_filenames = re.search(r'/video/(\d+)', video_url)
    video_filename = video_filenames.group(1)
    call_java_api("DOWNLOADING", {"video_id": video_id})
    downloader = TikTokDownloader(save_path=DOWNLOAD_DIR)
    video_path = downloader.download_video(video_url, custom_name=video_filename)
    if video_path and len(video_path) >= 10:
        call_java_api("DOWNLOAD", {"video_id": video_id, "video_path": video_path})
        return video_path
    else:
        call_java_api("ERROR", {"video_id": video_id, "errormsg": "视频下载失败"})
        return None

# ============================
# 6️⃣ 提取音频 & 关键帧
# ============================
def extract_audio_and_frames(video_path, video_id):
    """ 提取音频和关键帧 """
    audio_path = os.path.join(OUTPUT_MP3_DIR, f"{video_id}.mp3")
    ffmpeg.input(video_path).output(audio_path, format="mp3", acodec="libmp3lame").overwrite_output().run()
    keyframes = extract_keyframes(video_path, video_id)
    call_java_api("EXTRACT", {"video_id": video_id, "mp3": audio_path, "frames": keyframes})
    return audio_path, keyframes


# ============================
# 7️⃣ 提取关键帧
# ============================
def extract_keyframes(video_path, video_id):
    """ 提取关键帧 """
    # 2 进行场景检测
    scenes = detect(video_path, ContentDetector())

    # 3 获取每个转场的第一帧
    scene_folder = os.path.join(OUTPUT_IMG_DIR, video_id)  # 创建存放关键帧的文件夹
    # 自动创建文件夹（如果不存在）
    os.makedirs(scene_folder, exist_ok=True)
    scene_frames = []
    for scene in scenes:
        transition_time = scene[0].get_seconds()  # ✅ 获取秒数
        minutes = int(transition_time // 60)  # 计算分钟
        seconds = int(transition_time % 60)   # 计算剩余秒数
        time_str = f"{minutes:02d}-{seconds:02d}"  # 格式化为 MM-SS
        scene_image = os.path.join(scene_folder, f"scene_{time_str}.jpg")

        # 提取关键帧
        ffmpeg.input(video_path, ss=transition_time).output(scene_image, vframes=1).overwrite_output().run()
        scene_frames.append({"time": int(transition_time), "path": scene_image})
    return scene_frames


def ai_pipeline(audio_path, video_id):
    """ 负责 AI 解析 """
    try:
        # 这里等待你提供 Google AI 接口
        transcriber = GoogleSpeechTranscriber("zeta-courage-452114-u1")
        result = transcriber.transcribe_audio(audio_path)
        call_java_api("END", {"video_id": video_id, "ai_data": result})
    finally:
        global status
        status = False


# ============================
# 8️⃣ 调用 Java 接口
# ============================
def call_java_api(status, data):
    """ 调用 Java 系统 API，更新状态 """
    print(f"状态: {status}")
    print(f"data: {data}")
    java_api_url = "http://serverapp:8080/video-analysis/public/fghijklmnop/change-status"
    try:
        requests.post(java_api_url, json={"status": status, "data": data})
    except Exception as e:
        print(f"调用 Java 失败: {e}")


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)

# uvicorn index:app --host 0.0.0.0 --port 8000 --reload